package com.vip.seata.at.business.util;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@SuppressWarnings("ALL")
public class DateHelper {
	public static String STANDARD_YMD = "yyyy-MM-dd";
	public static String STANDARD_HOUR24 = "yyyy-MM-dd HH";
	public static String STANDARD_MINUTE24 = "yyyy-MM-dd HH:mm";
	public static String STANDARD_SECOND24 = "yyyy-MM-dd HH:mm:ss";
	public static String STANDARD_MILLISECONDS24 = "yyyy-MM-dd HH:mm:ss.SSS";
	
	public static String NOSPLIT_YMD = "yyyyMMdd";
	public static String NOSPLIT_HOUR24 = "yyyyMMddHH";
	public static String NOSPLIT_MINUTE24 = "yyyyMMddHHmm";
	public static String NOSPLIT_SECOND24 = "yyyyMMddHHmmss";
	public static String NOSPLIT_MILLISECONDS24 = "yyyyMMddHHmmssSSS";
	
	public static String CHINESE_YMD = "yyyy年MM月dd日";
	public static String CHINESE_HOUR24 = "yyyy年MM月dd日 HH时";
	public static String CHINESE_MINUTE24 = "yyyy年MM月dd日 HH时mm分";
	public static String CHINESE_SECOND24 = "yyyy年MM月dd日 HH时mm分ss秒";
	
	public static String TZ_SECOND24 = "yyyy-MM-dd'T'HH:mm:ss'Z'";
	public static String TZ_MILLISECONDS24 = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
	
	public static void main(String[] args) throws ParseException {
		/*Calendar calendar = Calendar.getInstance();
		SimpleDateFormat format = new SimpleDateFormat(DateHelper.STANDARD_YMD);
		Date now = format.parse("2018-09-22");
		
		Date start = format.parse("2018-09-2");
		Date days20Later = DateUtils.addDays(start, 19); //2018-09-21
		System.out.println(format.format(days20Later));
		Date end = days20Later;
		
		boolean isBetween = isBetween(now, start, end);
		System.out.println("isBetween:"+isBetween);
		
		Date next = getNextMonthStartDate(now);
		System.out.println(format.format(next));
		
		boolean after = start.before(start);
		System.out.println("after:"+after);*/
		
		Date now = new Date();
		Date compare = addDays(now, -3);
		compare = addHours(compare, 5);
		System.out.println(getBetweens(now, compare,TimeUnit.HOURS));
		
		System.out.println((getDay(new Date())));
		System.out.println(formatStandardMILLI(getStartOfDay(new Date(),2)));
	}

	public static String format(Date date,String format) {
		DateFormat df = new SimpleDateFormat(format);
		return df.format(date);
	}
	
	public static String formatStandardDay(Date date) {
		DateFormat df = new SimpleDateFormat(DateHelper.STANDARD_YMD);
		return df.format(date);
	}
	
	public static Date parseStandardDay(String yyyy_MM_dd) throws ParseException {
		DateFormat df = new SimpleDateFormat(DateHelper.STANDARD_YMD);
		return df.parse(yyyy_MM_dd);
	}

	public static String formatStandard24Second(Date date) {
		DateFormat df = new SimpleDateFormat(DateHelper.STANDARD_SECOND24);
		return df.format(date);
	}

	public static Date parseStandard24Second(String yyyy_MM_dd$HH_mm_ss) throws ParseException {
		DateFormat df = new SimpleDateFormat(DateHelper.STANDARD_SECOND24);
		return df.parse(yyyy_MM_dd$HH_mm_ss);
	}

	public static String formatNosplitDay(Date date) {
		DateFormat df = new SimpleDateFormat(DateHelper.NOSPLIT_YMD);
		return df.format(date);
	}

	public static Date parseNosplitDay(String yyyyMMdd) throws ParseException {
		DateFormat df = new SimpleDateFormat(DateHelper.NOSPLIT_YMD);
		return df.parse(yyyyMMdd);
	}

	public static String formatNosplit24Second(Date date) {
		DateFormat df = new SimpleDateFormat(DateHelper.NOSPLIT_SECOND24);
		return df.format(date);
	}

	public static Date parseNosplit24Second(String yyyyMMddHHmmss) throws ParseException {
		DateFormat df = new SimpleDateFormat(DateHelper.NOSPLIT_SECOND24);
		return df.parse(yyyyMMddHHmmss);
	}
	
	public static String formatStandardMILLI(Date date) {
		DateFormat df = new SimpleDateFormat(DateHelper.STANDARD_MILLISECONDS24);
		return df.format(date);
	}

	public static Date parseStandardMILLI(String yyyyMMddHHmmssSSS) throws ParseException {
		DateFormat df = new SimpleDateFormat(DateHelper.STANDARD_MILLISECONDS24);
		return df.parse(yyyyMMddHHmmssSSS);
	}

	/**
	 * now < compare ; return true
	 * now >= compare ; return false
	 * @param now
	 * @param compare
	 * @return
	 */
	public static boolean lt(Date now,Date compare) {
		return now.before(compare);
	}
	
	public static boolean le(Date now,Date compare) {
		return !now.after(compare);
	}
	
	/**
	 * now > compare ; return true
	 * now <= compare ; return false
	 * @param now
	 * @param compare
	 * @return
	 */
	public static boolean gt(Date now,Date compare) {
		return now.after(compare);
	}
	
	public static boolean ge(Date now,Date compare) {
		return !now.before(compare);
	}
	
	public static int getYear(Date date) {
		//return date.getYear();
		Calendar calendar= Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.YEAR);
	}
	
	public static int getMonth(Date date) {
		Calendar calendar= Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.MONTH);
	}
	
	public static int getDay(Date date) {
		Calendar calendar= Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.DAY_OF_MONTH);
	}
	
	public static int getHour(Date date) {
		Calendar calendar= Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.HOUR_OF_DAY);
	}
	
	public static int getMinute(Date date) {
		Calendar calendar= Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.MINUTE);
	}
	
	public static int getSecond(Date date) {
		Calendar calendar= Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.SECOND);
	}
	
	public static Date addYears(Date date, int amount) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.YEAR, amount);
        return c.getTime();
    }
	
	public static Date addMonths(Date date, int amount) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.MONTH, amount);
        return c.getTime();
    }
	
	public static Date addDays(Date date, int amount) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.DAY_OF_MONTH, amount);
        return c.getTime();
    }
	
	public static Date addHours(Date date, int amount) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.HOUR_OF_DAY, amount);
        return c.getTime();
    }
	
	public static Date addMinutes(Date date, int amount) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.MINUTE, amount);
        return c.getTime();
    }
	
	public static Date addSeconds(Date date, int amount) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.SECOND, amount);
        return c.getTime();
    }
	
	/**
	 * 描述:获取天的开始时间
	 * @return
	 */
    public static Date getStartOfDay(Date date,int addDays) {  
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DAY_OF_MONTH, addDays);
		calendar.set(Calendar.HOUR_OF_DAY, calendar.getActualMinimum(Calendar.HOUR_OF_DAY));
		calendar.set(Calendar.MINUTE, calendar.getActualMinimum(Calendar.MINUTE));
		calendar.set(Calendar.SECOND, calendar.getActualMinimum(Calendar.SECOND));
		calendar.set(Calendar.MILLISECOND, calendar.getActualMinimum(Calendar.MILLISECOND));
		return calendar.getTime();
    } 
    
	/**
	 * 描述:获取天的结束时间
	 * @return
	 */
    public static Date getEndOfDay(Date date,int addDays) {  
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DAY_OF_MONTH, addDays);
		calendar.set(Calendar.HOUR_OF_DAY, calendar.getActualMaximum(Calendar.HOUR_OF_DAY));
		calendar.set(Calendar.MINUTE, calendar.getActualMaximum(Calendar.MINUTE));
		calendar.set(Calendar.SECOND, calendar.getActualMaximum(Calendar.SECOND));
		calendar.set(Calendar.MILLISECOND, calendar.getActualMaximum(Calendar.MILLISECOND));
		return calendar.getTime();
    }  
    
	/**
	 * 描述:获取月的第一天.
	 * @return
	 */
	public static Date getMonthStartDate(Date current,int addMonth) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(current);
		calendar.add(Calendar.MONTH, addMonth);
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
		return calendar.getTime();
	}
	
	public static Date getMonthEndDate(Date current,int addMonth) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(current);
		calendar.add(Calendar.MONTH, addMonth);
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
		return calendar.getTime();
	}
	
    public static boolean isSameDay(Date now, Date compare) {
        if (now == null || compare == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
		Calendar cal1 = Calendar.getInstance();
		cal1.setTime(now);
		
		Calendar cal2 = Calendar.getInstance();
		cal2.setTime(compare);
        return cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) &&
               cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
               cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR);
    }
    
    /**
     * 计算两个日期之间的差值,存在正负数
     * @param now
     * @param compare
     * @param unit 差值的时间单位
     * @return
     */
    public static long getBetweens(Date now,Date compare,TimeUnit unit) {
    	long duration = now.getTime() - compare.getTime();
    	if(unit.equals(TimeUnit.DAYS)) {
    		return TimeUnit.MILLISECONDS.toDays(duration);
    	}
    	if(unit.equals(TimeUnit.HOURS)) {
    		return TimeUnit.MILLISECONDS.toHours(duration);
    	}
    	if(unit.equals(TimeUnit.MINUTES)) {
    		return TimeUnit.MILLISECONDS.toMinutes(duration);
    	}
    	if(unit.equals(TimeUnit.MILLISECONDS)) {
    		return TimeUnit.MILLISECONDS.toMillis(duration);
    	}
    	if(unit.equals(TimeUnit.MICROSECONDS)) {
    		return TimeUnit.MILLISECONDS.toMicros(duration);
    	}
    	if(unit.equals(TimeUnit.NANOSECONDS)) {
    		return TimeUnit.MILLISECONDS.toNanos(duration);
    	}
    	throw new IllegalArgumentException("TimeUnit parameter illegal");
    }
	
	/**
	 *  判断 now 是否在 start 和 end 时间范围内（start<=nowDate<=end天判断依据）
	 * @param now
	 * @param start
	 * @param end
	 * @return
	 * @throws ParseException
	 */
	public static boolean isBetween(Date now, Date start, Date end) {
		long thisMills = now.getTime();
		long beginMills = start.getTime();
		long endMills = end.getTime();
		return thisMills >= Math.min(beginMills, endMills) && thisMills <= Math.max(beginMills, endMills);
	}
	
	/**
	 * 判断时间区间A 和 B 是否有重叠
	 * @param aStart
	 * @param aEnd
	 * @param bStart
	 * @param bEnd
	 * @return
	 */
	public static boolean isOverlap(Date aStart,Date aEnd,Date bStart,Date bEnd) {
		if( isBetween(aStart, bStart, bEnd) || isBetween(aEnd, bStart, bEnd) ){
			return true;
		}
		if( isBetween(bStart, aStart, aEnd) || isBetween(bEnd, aStart, aEnd) ){
			return true;
		}
		return false;
	}

}
